package backend.network.server;

import interfaces.rmi.client.IClientCallBack;
import interfaces.rmi.server.IModule;
import interfaces.rmi.server.IServerApi;

import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import backend.game.engine.Engine;
import backend.network.server.load.ConnectionManager;

public class Server extends UnicastRemoteObject implements IServerApi
{

	private static final long serialVersionUID = 1L;
	public static final String NAME = "rmiserver";
	private static final int PORT = 1099;
	private static Registry registry;

	private static int tick = 5000;

	private ConnectionManager conManager = null;
	private Vector<IModule> iModules = null;

	private int counter = 0;

	public Server() throws RemoteException, AlreadyBoundException
	{
		super();

		conManager = new ConnectionManager();
		iModules = new Vector<IModule>();

		startRegistry();
		registerObject(NAME, this);

		System.out.println("RMIServer \"" + NAME + "\" alive.");

		// // XXX properties file
		iModules.add(new Engine());

		loop();
	}

	public static void startRegistry() throws RemoteException
	{
		// create in server registry
		registry = java.rmi.registry.LocateRegistry.createRegistry(PORT);
	}

	public static void registerObject(String name, Remote remoteObj) throws RemoteException, AlreadyBoundException
	{
		registry.bind(name, remoteObj);
		System.out.println("Registered: " + name + " -> " + remoteObj.getClass().getName() + "[" + remoteObj + "]");
	}

	private void loop() throws RemoteException
	{
		while (true)
		{
			conManager.incCounter();
			Collection<IClientCallBack> collection = conManager.getCollection();
			int connections = collection.size();

			for (IClientCallBack iClientCallBack : collection)
			{
				System.out.println("Processing connection " + iClientCallBack);

				iClientCallBack.chat(String.valueOf(System.currentTimeMillis()));

				for (IModule iModule : iModules)
				{
					iModule.process(iClientCallBack);
				}
			}

			System.out.println("Connections: " + connections);
			try
			{
				conManager.decCounter();
				Thread.sleep(tick);
			} catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}

	@Override
	public synchronized Data incrementCounter(Data value) throws RemoteException
	{
		counter += value.getValue();
		return new Data(counter);
	}

	@Override
	public void login(IClientCallBack connection, String name) throws RemoteException
	{
		conManager.login(connection, name);
	}

	@Override
	public void chat(String name, String s) throws RemoteException
	{
		for (Iterator<IClientCallBack> i = conManager.getCollection().iterator(); i.hasNext();)
		{
			IClientCallBack client = i.next();
			client.sendMessage(name, s);
		}
	}

	@Override
	public void leave(IClientCallBack n, String name) throws RemoteException
	{
		conManager.leave(n, name);
	}

}